package com.eis.admin.mvc.controller;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.eis.admin.mvc.bean.FunctionBean;
import com.eis.admin.mvc.bean.FunctionParametersBean;
import com.eis.admin.mvc.bean.xml.ConnectorConfigureBean;
import com.eis.admin.mvc.bean.xml.ConnectorConfigureParaBean;
import com.eis.admin.mvc.bean.xml.FunctionParameter;
import com.eis.admin.mvc.common.utils.MVCConstants;
import com.eis.admin.mvc.controller.base.MVCBaseController;
import com.eis.exception.EisSysException;
import com.eis.persist.dao.BizSystemDAO;
import com.eis.persist.dao.UserFunctionDAO;
import com.eis.persist.dao.impl.BizSystemDAOImpl;
import com.eis.persist.dao.impl.UserFunctionDAOImpl;
import com.eis.persist.model.bizsystem.PersistBizSystem;
import com.eis.persist.model.bizsystem.PersistConnectorConfigure;
import com.eis.persist.model.function.PersistFunctionLayoutGroup;
import com.eis.persist.model.function.PersistFunctionParameter;
import com.eis.persist.model.function.PersistFunctionType;
import com.eis.persist.model.user.PersistUser;
import com.eis.thirdsys.connector.ThirdSysConnectorFactory;
import com.eis.thirdsys.connector.conf.ConnectorConfig;
import com.eis.util.XmlUtil;

@Controller
public class FunctionAdminController extends MVCBaseController {
	private static final Logger logger = LoggerFactory
			.getLogger(FunctionAdminController.class);
	private UserFunctionDAO userFunctionDAO;
	private BizSystemDAO bizSystemLoadDAO;
	private XmlUtil xmlUtil;
	public void setXmlUtil(XmlUtil xmlUtil) {
		this.xmlUtil = xmlUtil;
	}

	@Override
	public void setFunctionDataSource(JdbcTemplate functionDataSource) {
		this.functionDataSource = functionDataSource;
		userFunctionDAO = new UserFunctionDAOImpl(this.functionDataSource);
		bizSystemLoadDAO = new BizSystemDAOImpl(this.functionDataSource);
	}
	
	@RequestMapping(value = "/functionIntroduction")
	public ModelAndView functionIntroduction(Model model, HttpServletRequest request) {
		return new ModelAndView("/function/functionIntroduction");
	}
	
	@RequestMapping(value = "/functionHome")
	public ModelAndView functionHome(@ModelAttribute("searchFunction") FunctionBean function, Model model, HttpServletRequest request) {
		FunctionBean filter = null;
		if (function != null && function.isFilterable()) {
			filter = function;
		}
		
		PersistUser currentUser = super.getCurrentUser(request);
		
		List<FunctionBean> functions = userFunctionDAO.getFunctionsForList(currentUser.getBizGroup().getId(), 1, 100, filter);

		model.addAttribute("functionList", functions);
		
		List<PersistFunctionType> types = userFunctionDAO.getFunctionTypes();
		model.addAttribute("functionTypes", types);

		return new ModelAndView("/function/functionHome", "command", function);
	}
	
	@RequestMapping(value = "/createFunction")
	public ModelAndView createFunction(Model model, HttpServletRequest request) {
		// get bizsysid from request
		int bizSysId = 0;
		try {
			bizSysId = Integer.valueOf(request.getParameter("bizsysid"));
		} catch (Throwable t) {
		}

		if (bizSysId > 0) {
			// load BizSystem
			PersistBizSystem system = bizSystemLoadDAO.getBizSystem(bizSysId);
			if (system != null) {
				List<PersistFunctionType> types = userFunctionDAO.getFunctionTypes();
				model.addAttribute("functionTypes", types);
				
				List<PersistConnectorConfigure> connectorConfs= bizSystemLoadDAO.getConnectorConfigs(bizSysId);
				List<ConnectorConfigureBean> connectorConfigDisplayList = new ArrayList<ConnectorConfigureBean>();

				try {
					ThirdSysConnectorFactory thirdSysConnectorFactory = new ThirdSysConnectorFactory(system.getConnectorStaticsClassName());
					if (connectorConfs != null && connectorConfs.size() > 0) {
						for (PersistConnectorConfigure pconfig : connectorConfs) {
							ConnectorConfigureBean parsed = (ConnectorConfigureBean) xmlUtil.parseXml(pconfig.getConfigXml());
							ConnectorConfig config = thirdSysConnectorFactory.newConnectorConfig();
							for (ConnectorConfigureParaBean bean : parsed.getConnectorConfigureParaBean()) {
								config.setOneConf(bean.getKey(), bean.getValue());
							}
							
							parsed.setThirdDisplay(config.toDisplayString());
							parsed.setConnectorId(pconfig.getId());
							
							connectorConfigDisplayList.add(parsed);
						}
					}
				} catch (Exception e) {
					logger.error("Oh GOD!", e);
				} 
				
				model.addAttribute("functionConnConfs", connectorConfigDisplayList);
				
				List<PersistFunctionLayoutGroup> layoutGroups = userFunctionDAO.getFunctionLayoutGroups(bizSysId);
				model.addAttribute("functionLayoutGroups", layoutGroups);

				model.addAttribute("bizSystemTypes",MVCConstants.BIZ_SYSTEM_TYPE_LIST);
				
				model.addAttribute("selectedBizSystem", system);

				return new ModelAndView("/function/createFunction", "command", new FunctionBean());
			}
		}

		List<PersistBizSystem> bizSystemList = bizSystemLoadDAO
				.getAllBizSystems();
		model.addAttribute("bizSystemList", bizSystemList);
		model.addAttribute("targetpath", "createFunction");

		return new ModelAndView("/function/selectBizsys", "command", new PersistBizSystem());
	}
	
	@RequestMapping(value = "/disableFunction")
	public ModelAndView disableFunction(Model model, HttpServletRequest request) {
		PersistUser currentUser = (PersistUser) request.getSession().getAttribute(
				MVCConstants.USER_SESSION_KEY);
		UserFunctionDAO userFunctionDAO1 = new UserFunctionDAOImpl(this.functionDataSource, currentUser.getName());
		
		String functionDbId = request.getParameter("id");
		String isenable = request.getParameter("isenable");
		boolean active = "true".equals(isenable);
		try {
			if (userFunctionDAO1.disableOrEnableFunctionById(Integer.parseInt(functionDbId), active)) {
				String message = active ? "PersistFunction have been enabled!" : "PersistFunction have been disabled!";
				return new ModelAndView(
						"redirect:" + appPrefix + "/functionHome",
						prepareRedirectWarnMessage(message));
			} else {
				logger.info("No function found when disable/enable function, id: " + functionDbId);
				String message = active ? "No function found for enable!" : "No function found for disable!";
				return new ModelAndView(
						"redirect:" + appPrefix + "/functionHome",
						prepareRedirectWarnMessage(message));
			}
		} catch (Throwable t) {
			logger.error("Error when disable/enable function, id: " + functionDbId, t);
			String message = active ? "Error occured when enable function!" : "Error occured when disable function!";
			return new ModelAndView(
					"redirect:" + appPrefix + "/functionHome",
					prepareRedirectErrorMessage(message));
		}
	}
	
	@RequestMapping(value = "/submitCreateFunction")
	public ModelAndView submitCreateFunction(Model model,
			@ModelAttribute("createFunction") FunctionBean functionBean,
			HttpServletRequest request) {
		PersistUser currentUser = (PersistUser) request.getSession().getAttribute(
				MVCConstants.USER_SESSION_KEY);
		UserFunctionDAO userFunctionDAO1 = new UserFunctionDAOImpl(this.functionDataSource, currentUser.getName());

		// TODO: validate
		userFunctionDAO1.createFunction(functionBean);
		return new ModelAndView("redirect:" + appPrefix + "/functionHome", prepareRedirectWarnMessage("PersistFunction '" + functionBean.getFunctionID() + "::"
				+ functionBean.getFunctionName()
				+ "' have been created successfully!"));
	}
	
	@RequestMapping(value = "/editFunction")
	public ModelAndView editFunction(Model model, HttpServletRequest request) {
		String functionId = request.getParameter("id");
		
		FunctionBean functionData = userFunctionDAO.getFunctionforEdit(functionId);
		
		if (functionData == null) {
			String message = "You tried to edit a function which does not exist! Function id is " + functionId;
			return new ModelAndView("redirect:" + appPrefix + "/functionHome", prepareRedirectErrorMessage(message));
		} else {
			// List connector configures
			// load BizSystem
			PersistBizSystem system = bizSystemLoadDAO.getBizSystem(functionData.getBizsysId());
			if (system != null) {
				List<PersistFunctionType> types = userFunctionDAO.getFunctionTypes();
				model.addAttribute("functionTypes", types);
				
				List<PersistFunctionLayoutGroup> layoutGroups = userFunctionDAO.getFunctionLayoutGroups(system.getId());
				model.addAttribute("functionLayoutGroups", layoutGroups);
				
				model.addAttribute("bizSystemTypes", MVCConstants.BIZ_SYSTEM_TYPE_LIST);
				
				List<PersistConnectorConfigure> connectorConfs = bizSystemLoadDAO.getConnectorConfigs(functionData.getBizsysId());
				List<ConnectorConfigureBean> connectorConfigDisplayList = new ArrayList<ConnectorConfigureBean>();
				try {
					ThirdSysConnectorFactory thirdSysConnectorFactory = new ThirdSysConnectorFactory(system.getConnectorStaticsClassName());
					if (connectorConfs != null && connectorConfs.size() > 0) {
						for (PersistConnectorConfigure pconfig : connectorConfs) {
							ConnectorConfigureBean parsed = (ConnectorConfigureBean) xmlUtil.parseXml(pconfig.getConfigXml());
							ConnectorConfig config = thirdSysConnectorFactory.newConnectorConfig();
							for (ConnectorConfigureParaBean bean : parsed.getConnectorConfigureParaBean()) {
								config.setOneConf(bean.getKey(), bean.getValue());
							}

							parsed.setThirdDisplay(config.toDisplayString());
							parsed.setConnectorId(pconfig.getId());

							connectorConfigDisplayList.add(parsed);
						}
					}
				} catch (Exception e) {
					logger.error("Oh GOD!", e);
				}

				model.addAttribute("functionConnConfs", connectorConfigDisplayList);

				model.addAttribute("bizSystemTypes", MVCConstants.BIZ_SYSTEM_TYPE_LIST);

				model.addAttribute("selectedBizSystem", system);
			}
			
			return new ModelAndView("/function/editFunction", "command", functionData); 
		}
	}
	
	@RequestMapping(value = "/submitEditFunction")
	public ModelAndView submitEditFunction(Model model,
			@ModelAttribute("editFunction") FunctionBean functionBean,
			HttpServletRequest request) {
		PersistUser currentUser = (PersistUser) request.getSession().getAttribute(
				MVCConstants.USER_SESSION_KEY);
		UserFunctionDAO userFunctionDAO1 = new UserFunctionDAOImpl(this.functionDataSource, currentUser.getName());

		// TODO: validate
		userFunctionDAO1.editFunction(functionBean);
		return new ModelAndView("redirect:" + appPrefix + "/functionHome", prepareRedirectWarnMessage("PersistFunction '" + functionBean.getFunctionID() + "::"
				+ functionBean.getFunctionName()
				+ "' have been updated successfully!"));
	}
	
	@RequestMapping(value = "/actionerGroupList")
	public ModelAndView actionerGroupList(Model model, HttpServletRequest request) {
		PersistUser currentUser = (PersistUser) request.getSession().getAttribute(
				MVCConstants.USER_SESSION_KEY);
		
		// get bizsysid from request
		int bizSysId = 0;
		try {
			bizSysId = Integer.valueOf(request.getParameter("bizsysid"));
		} catch (Throwable t) {
		}

		if (bizSysId > 0) {
			// load BizSystem
			PersistBizSystem system = bizSystemLoadDAO.getBizSystem(bizSysId);
			if (system != null) {
				UserFunctionDAO userfunctionDAO = new UserFunctionDAOImpl(
						this.functionDataSource, currentUser.getName());
				List<PersistFunctionLayoutGroup> actionerGroupList = userfunctionDAO.getFunctionLayoutGroups(bizSysId);
				model.addAttribute("actionerGroupList", actionerGroupList);
				model.addAttribute("selectedBizSystem", system);
				return new ModelAndView("/function/actionerGroupList", "command",
						new PersistFunctionLayoutGroup());
			}
		}

		List<PersistBizSystem> bizSystemList = bizSystemLoadDAO
				.getAllBizSystems();
		model.addAttribute("bizSystemList", bizSystemList);
		model.addAttribute("targetpath", "actionerGroupList");

		return new ModelAndView("/function/selectBizsys", "command", new PersistBizSystem());
	}
	
	@RequestMapping(value = "/addActionGroup")
	public ModelAndView addActionGroup(@ModelAttribute("newActionerGroupform") PersistFunctionLayoutGroup actionerGroup, Model model, HttpServletRequest request) {
		PersistUser currentUser = (PersistUser) request.getSession().getAttribute(
				MVCConstants.USER_SESSION_KEY);
		UserFunctionDAO userfunctionDAO = new UserFunctionDAOImpl(this.functionDataSource, currentUser.getName());
		String message = "Operation done";
		try {
			userfunctionDAO.addFunctionLayoutGroup(actionerGroup);
			return new ModelAndView(
					"redirect:" + appPrefix + "/actionerGroupList?bizsysid=" + actionerGroup.getBizsysId(),
					prepareRedirectWarnMessage(message));
		} catch (EisSysException e) {
			message = e.getErrorCode() + ", " + e.getMessage();
			return new ModelAndView(
					"redirect:" + appPrefix + "/actionerGroupList?bizsysid=" + actionerGroup.getBizsysId(),
					prepareRedirectErrorMessage(message));
		}
	}

	@RequestMapping(value = "/functionPrameter")
	public ModelAndView functionPrameter(Model model, HttpServletRequest request) {
		// get function id from request
		String functionId = "";
		try {
			functionId = request.getParameter("functionId");
		} catch (Throwable t) {}

		if (functionId != null && functionId.length() > 0) {
			// load function
			FunctionBean function = userFunctionDAO.getFunctionforEdit(functionId);
			
			
			try {
				ThirdSysConnectorFactory thirdSysConnectorFactory = new ThirdSysConnectorFactory(function.getBizsysConnectorStaticsClassName());

				if (function != null) {
					FunctionParametersBean bean = new FunctionParametersBean();
					List<PersistFunctionParameter> parameters = userFunctionDAO.getFunctionPramaters(function.getId());
					List<FunctionParameter> prabean = new ArrayList<FunctionParameter>();
					for (PersistFunctionParameter pf : parameters) {
						FunctionParameter p = new FunctionParameter();
						p.setDeleted(0);
						p.setFunctionDBID(pf.getFunctionDBID());
						p.setId(pf.getId());
						p.setElements(((FunctionParameter) xmlUtil.parseXml(pf.getParameterXMl())).getElements());
						prabean.add(p);
					}
					
					bean.setFunctionId(functionId);
					bean.setParameters(null);
					bean.setFunctionName(function.getFunctionName());
					bean.setFunctionDBID(function.getId());
					bean.setParameterDefine(thirdSysConnectorFactory.getConnectorStatics().getParameterDefine());
					bean.setParameters(prabean);
					return new ModelAndView("/function/functionPrameter", "command", bean);
				}
			} catch (Exception e) {
				logger.error("", e);
			}

		}

		return new ModelAndView(
				"redirect:" + appPrefix + "/functionHome",
				prepareRedirectErrorMessage("Please select a function to edit parameters!"));
	}
	
	@RequestMapping(value = "/saveFunctionParameters")
	public ModelAndView saveFunctionParameters(@ModelAttribute("functionParameterForm") FunctionParametersBean functionParameters,Model model, HttpServletRequest request) {
		// get function id from request
		PersistUser currentUser = (PersistUser) request.getSession().getAttribute(
				MVCConstants.USER_SESSION_KEY);

		if (functionParameters != null && functionParameters.getFunctionId() != null) {
			UserFunctionDAO dao = new UserFunctionDAOImpl(functionDataSource, currentUser.getName());
			try {
				List<PersistFunctionParameter> parameters = new ArrayList<PersistFunctionParameter>();
				for (FunctionParameter p : functionParameters.getParameters()) {
					PersistFunctionParameter pf = new PersistFunctionParameter();
					pf.setDeleted(p.getDeleted());
					pf.setFunctionDBID(p.getFunctionDBID());
					pf.setId(p.getId());
					pf.setParameterXMl(xmlUtil.toXml(p));
					parameters.add(pf);
				}
				
				dao.saveFunctionPramaters(functionParameters.getFunctionDBID(),parameters );
				
				return new ModelAndView(
						"redirect:" + appPrefix + "/functionPrameter?functionId=" + functionParameters.getFunctionId(),
						prepareRedirectWarnMessage("Save complete!"));
			} catch (EisSysException e) {
				return new ModelAndView(
						"redirect:" + appPrefix + "/functionPrameter?functionId=" + functionParameters.getFunctionId(),
						prepareRedirectErrorMessage(e.getErrorCode() + ", " + e.getMessage()));
			}

		}

		return new ModelAndView(
				"redirect:" + appPrefix + "/functionHome",
				prepareRedirectErrorMessage("Please select a function to edit parameters!"));
	}
	
}
